//
//  MBMacros.h
//  mZero-iOS
//
//  Created by catch on 16/5/30.
//  Copyright © 2016年 Shenzhen Maker Works Technology Co., Ltd. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

/**
 *  设备、版本
 */
#define IsPhone                 (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IsPad                   (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IosAppVersion           [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]
#define IosBundleID             [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]
#define IosVersion              [[[UIDevice currentDevice] systemVersion] floatValue]
#define IsIOS7                  ([[[[UIDevice currentDevice] systemVersion] substringToIndex:1] intValue]>=7)
#define IsIOS8                  ([[[[UIDevice currentDevice] systemVersion] substringToIndex:1] intValue]>=8)
#define IsIOS9                  ([[[[UIDevice currentDevice] systemVersion] substringToIndex:1] intValue]>=9)

/**
 *  普通常量
 */
#define KPI                         (3.1415926)
#define KWHMin                      ([UIScreen mainScreen].bounds.size.height < [UIScreen mainScreen].bounds.size.width ? [UIScreen mainScreen].bounds.size.height : [UIScreen mainScreen].bounds.size.width)
#define KWHMax                      ([UIScreen mainScreen].bounds.size.height > [UIScreen mainScreen].bounds.size.width ? [UIScreen mainScreen].bounds.size.height : [UIScreen mainScreen].bounds.size.width)
#define KHeight                     ([UIScreen mainScreen].bounds.size.height)
#define KWidth                      ([UIScreen mainScreen].bounds.size.width)
#define KStatusBarHeight            ([[UIApplication sharedApplication] statusBarFrame].size.height)
#define MB_FLOAT_EQUAL_CRITERION    (1e-6)

/**
 *  常用方法
 */
#define MPathHome                   [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
#define MFont(s)                    ([UIFont fontWithName:@"OpenSans" size:s] ? [UIFont fontWithName:@"OpenSans" size:s] : [UIFont systemFontOfSize:s])
#define MFontBlod(s)                ([UIFont fontWithName:@"OpenSans-Bold" size:s] ? [UIFont fontWithName:@"OpenSans-Bold" size:s] : [UIFont systemFontOfSize:s])
#define MB_FLOAT_EQUAL(x,y)         (fabs(x-y)<MB_FLOAT_EQUAL_CRITERION)

/**
 *  使用方法:
 *  .h文件  single_interface(class)
 *  .m文件  single_implementation(class)
 */

// .h
#define single_interface(class)  + (class *)sharedInstance;

// .m
// \ 代表下一行也属于宏
// ## 是分隔符
#define single_implementation(class) \
static class *instance; \
\
+ (class *)sharedInstance \
{ \
if (instance == nil) { \
instance = [[self alloc] init]; \
} \
return instance; \
} \
\
+ (id)allocWithZone:(NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
instance = [super allocWithZone:zone]; \
}); \
return instance; \
}


/**
 避免block循环引用
 
 Example:
 @weakify(self)
 [self doSomething^{
 @strongify(self)
 if (!self) return;
 ...
 }];
 
 */
#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
#endif
#endif
#endif

#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
#endif
#endif
#endif


/**
 加在 category implementation 文件中使得用category文件时不需要-all_load or -force_load
 More info: http://developer.apple.com/library/mac/#qa/qa2006/qa1490.html .
 *******************************************************************************
 Example:
 MBSYNTH_DUMMY_CLASS(NSString_YYAdd)
 */
#ifndef MBSYNTH_DUMMY_CLASS
#define MBSYNTH_DUMMY_CLASS(_name_) \
@interface MBSYNTH_DUMMY_CLASS ## _name_ : NSObject @end \
@implementation MBSYNTH_DUMMY_CLASS ## _name_ @end
#endif


/**
 为categories增加引用型属性
 
 @param association  ASSIGN / RETAIN / COPY / RETAIN_NONATOMIC / COPY_NONATOMIC  see in objc_AssociationPolicy
 @warning #import <objc/runtime.h>
 *******************************************************************************
 Example:
 @interface NSObject (MyAdd)
 @property (nonatomic, retain) UIColor *myColor;
 @end
 
 #import <objc/runtime.h>
 @implementation NSObject (MyAdd)
 MBSYNTH_DYNAMIC_PROPERTY_OBJECT(myColor, setMyColor, RETAIN, UIColor *)
 @end
 */
#ifndef MBSYNTH_DYNAMIC_PROPERTY_OBJECT
#define MBSYNTH_DYNAMIC_PROPERTY_OBJECT(_getter_, _setter_, _association_, _type_) \
- (void)_setter_ : (_type_)object { \
[self willChangeValueForKey:@#_getter_]; \
objc_setAssociatedObject(self, _cmd, object, OBJC_ASSOCIATION_ ## _association_); \
[self didChangeValueForKey:@#_getter_]; \
} \
- (_type_)_getter_ { \
return objc_getAssociatedObject(self, @selector(_setter_:)); \
}
#endif


/**
 为categories增加c语言型属性
 
 @warning #import <objc/runtime.h>
 *******************************************************************************
 Example:
 @interface NSObject (MyAdd)
 @property (nonatomic, retain) CGPoint myPoint;
 @end
 
 #import <objc/runtime.h>
 @implementation NSObject (MyAdd)
 MBSYNTH_DYNAMIC_PROPERTY_CTYPE(myPoint, setMyPoint, CGPoint)
 @end
 */
#ifndef MBSYNTH_DYNAMIC_PROPERTY_CTYPE
#define MBSYNTH_DYNAMIC_PROPERTY_CTYPE(_getter_, _setter_, _type_) \
- (void)_setter_ : (_type_)object { \
[self willChangeValueForKey:@#_getter_]; \
NSValue *value = [NSValue value:&object withObjCType:@encode(_type_)]; \
objc_setAssociatedObject(self, _cmd, value, OBJC_ASSOCIATION_RETAIN); \
[self didChangeValueForKey:@#_getter_]; \
} \
- (_type_)_getter_ { \
_type_ cValue = { 0 }; \
NSValue *value = objc_getAssociatedObject(self, @selector(_setter_:)); \
[value getValue:&cValue]; \
return cValue; \
}
#endif


